import React, { useEffect, useMemo, useRef, useState } from 'react';
import classNames from 'classnames';

import keyCode from './keyCode';

const noop = () => {};

const scrollIntoViewIfNeeded = findMe => {
    const contRect = findMe.parentNode.parentNode.getBoundingClientRect();
    const findMeRect = findMe.getBoundingClientRect();
    if (
        findMeRect.top < contRect.top ||
        findMeRect.bottom > contRect.bottom ||
        findMeRect.right > contRect.right ||
        findMeRect.left < contRect.left
    ) findMe.scrollIntoView();
};

const ConditionSelector = React.forwardRef(
    (
        {
            conditions,
            showSelect,
            onChange = noop,
            onKeyDown = noop,
            onKeyUp = noop,
            afterShowSelect = noop,
            afterHideSelect = noop,
            placeholder = '请输入'
        },
        ref
    ) => {
        const [searchValue, setSearchValue] = useState();
        const [highlightIndex, setHighlightIndex] = useState(0);
        const [show, setShow] = useState(showSelect);
        const inputRef = useRef(null);
        const conditionListRef = useRef(null);
        const oldRef = useRef({ old: null });

        const filterConditions = useMemo(
            () =>
                !searchValue
                    ? conditions
                    : conditions.filter(item => item.name.toLowerCase().includes(searchValue.toLowerCase())),
            [conditions, searchValue]
        );

        const handleInputChange = event => {
            setSearchValue(event.target.value);
            setHighlightIndex(0);
        };

        const handleChange = item => {
            onChange(item);
        };

        const handleKeyDown = event => {
            oldRef.current.old = searchValue;
            const keyResult = onKeyDown(event, oldRef.current.old);

            if (keyResult === false) {
                return;
            }

            // 向下键
            if (event.which === keyCode.DOWN) {
                const lastIndex = filterConditions.length - 1;
                setHighlightIndex(highlightIndex < lastIndex ? highlightIndex + 1 : lastIndex);
                return;
            }

            // 向上键
            if (event.which === keyCode.UP) {
                setHighlightIndex(highlightIndex > 0 ? highlightIndex - 1 : 0);
                return;
            }

            // 按下回车键
            if (event.which === keyCode.ENTER) {
                handleChange(filterConditions[highlightIndex]);
                event.preventDefault();
            }
        };

        const handleKeyUp = event => {
            const keyResult = onKeyUp(event, oldRef.current.old);
            if (keyResult === false) {
                return;
            }

            // 按ESC
            if (event.which === 27) {
                setShow(false);
            }

            console.log('condition select handleKeyUp');
        };

        useEffect(() => {
            if (show) {
                afterShowSelect();
                window.setTimeout(() => {
                    setSearchValue('');
                    inputRef.current.value = '';
                    inputRef.current.focus();
                }, 100);
            } else {
                afterHideSelect();
            }
        }, [show, inputRef]);

        useEffect(() => {
            setShow(showSelect);
        }, [showSelect]);

        useEffect(() => {
            const conditionBox = conditionListRef.current;

            if (conditionBox && highlightIndex != null) {
                const highlightNode = conditionBox.querySelector('.condition-item--highlight');

                if (!highlightNode) {
                    return;
                }

                if (highlightNode.scrollIntoViewIfNeeded) {
                    highlightNode.scrollIntoViewIfNeeded();
                } else {
                    scrollIntoViewIfNeeded(highlightNode);
                }
            }
        }, [highlightIndex]);

        return (
            <div ref={ref} id="condition" className={classNames('condition', { hide: !show })}>
                <input
                    ref={inputRef}
                    type="input"
                    className="condition-input"
                    placeholder={placeholder}
                    onKeyDown={handleKeyDown}
                    onKeyUp={handleKeyUp}
                    onChange={handleInputChange}
                    onBlur={() => setTimeout(() => setShow(false), 300)}
                />
                <div ref={conditionListRef} className={classNames('condition-list')}>
                    <ul>
                        {filterConditions.map((item, index) => (
                            <li
                                key={item.value}
                                value={item.value}
                                onClick={() => handleChange(item)}
                                className={classNames('condition-item', {
                                    'condition-item--highlight': index === highlightIndex
                                })}
                            >
                                {item.name}
                            </li>
                        ))}
                    </ul>
                </div>
            </div>
        );
    }
);

export default ConditionSelector;
